home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 9
/
FM Towns Free Software Collection 9.iso
/
t_os
/
tool
/
extdrv
/
src
/
dir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-16
|
8KB
|
357 lines
#include "extdrv.h"
#include "ctype.h"
#include "file.h"
#include "dir.h"
#include "buffer.h"
#include "dos.h"
#include "extern.h"
extern u_char *dmabuf;
extern u_long ldmabuf;
extern u_short dmabufsize;
struct pbuf far *pdirbuf;
dir_open(struct drvinfo far *d, char *path, struct dirbuf *bp)
{
u_char *s, *t, *p;
u_char buf[MAX_PATH_LEN];
bp->drv = d;
bp->id = bp->fat = bp->slot = 0;
if (dir_bread(bp) < 0)
return (-1);
strcpy(buf, path);
t = &buf[1];
for (s = t; *s != '\0'; s++){
if (issjis1(s[0]) && issjis2(s[1]))
s++;
else if (*s == '\\'){
p = t;
*s = '\0';
if (descend(bp, p) < 0)
return(-1);
t = s + 1;
}
}
return (descend(bp, t));
}
static descend(struct dirbuf *bp, char *path)
{
u_short start;
struct dirent far *dir;
char pattern[12];
if (*path == '\0')
return(0);
#ifdef DEBUG
auxputs("descend:");
#endif
expand(path, pattern);
#ifdef DEBUG
pattern[11] = '\0';
auxputs(pattern);
auxputs(" ");
#endif
while ((dir = dir_read(bp)) != DIR_EOF){
if (dir->name[0] == IS_EMPTY)
break;
if (dir->name[0] == IS_DELETED)
continue;
if (!(dir->attr & IS_DIR))
continue;
if (dir->name[0] == '.')
continue;
if (match(dir->name, pattern)){
start = dir->start;
/* if '..' points to root */
if (start == 0 && strcmp(path, "..") == 0){
bp->id = bp->fat = bp->slot = 0;
return(dir_bread(bp));
}
bp->id = bp->fat = start;
bp->slot = 0;
return (dir_bread(bp));
}
}
#ifdef DEBUG
auxputs("\r\n");
#endif
/*
* If path is '.' or '..', but they weren't found, then you must be
* at root.
*/
if (!strcmp(path, ".") || !strcmp(path, "..")){
bp->id = bp->fat = bp->slot = 0;
return (dir_bread(bp));
}
return(-1);
}
struct dirent far *dir_read(struct dirbuf *dbuf)
{
int i;
struct pbuf far *pp;
u_long src;
if (dbuf->slot == dbuf->n_entry){
if (dir_next(dbuf) != 0)
return (NULL);
dbuf->slot = 0;
}
/* search primary buffer */
for (i = 0, pp = pdirbuf; i < 2; i++, pp++)
if (pp->drv==dbuf->drv && pp->id==dbuf->id && pp->fat==dbuf->fat)
break;
if (dbuf->n_entry < 0 && i != 2){
if (dbuf->id == 0){
dbuf->buf.rp = pp->buffer.rdir;
dbuf->n_entry = dbuf->buf.rp->n_entry;
} else {
dbuf->buf.bp = pp->buffer.buf;
dbuf->n_entry = dbuf->drv->dirsec * dbuf->drv->cluster;
}
}
if (i == 2 ||
(dbuf->slot < pp->offset || pp->offset+pp->n_entry <= dbuf->slot)){
if (i == 2){ /* not found */
pp = pdirbuf;
if (pp->age == 0)
pp++;
if (pp->drv != NULL){
if (pp->id == 0)
pp->buffer.rdir->pp = NULL;
else
pp->buffer.buf->pp = NULL;
}
if (dir_bread(dbuf) < 0){
pp->drv = NULL;
return (DIR_EOF);
}
pp->drv = dbuf->drv;
pp->id = dbuf->id;
pp->fat = dbuf->fat;
if (dbuf->id == 0){
pp->buffer.rdir = dbuf->buf.rp;
pp->buffer.rdir->pp = pp;
} else {
pp->buffer.buf = dbuf->buf.bp;
pp->buffer.buf->pp = pp;
}
}
pp->offset = dbuf->slot / NDIRPBUF;
pp->offset *= NDIRPBUF;
src = (dbuf->id == 0) ? dbuf->buf.rp->buf : dbuf->buf.bp->buf;
src += pp->offset * sizeof (struct dirent);
xcopy(src, laddr(pp->data), PBUFSIZE);
if ((pp->n_entry = NDIRPBUF) > dbuf->n_entry - pp->offset)
pp->n_entry = dbuf->n_entry - pp->offset;
}
pp->age = 0;
if (pp == pdirbuf)
(pdirbuf+1)->age = 1;
else
pdirbuf->age = 1;
return ((struct dirent far *)pp->data + (dbuf->slot++ - pp->offset));
}
struct dirent far *dir_seek(struct dirbuf *dbuf)
{
struct dirent far *dir;
dbuf->n_entry = -1;
dir = dir_read(dbuf);
dbuf->slot--;
return (dir);
}
dir_write(struct dirbuf *dbuf, struct dirent far *dir)
{
int i;
struct pbuf far *pp;
u_long dst;
#ifdef DEBUG
auxputs("dir_write ");
auxprinthex((u_long)dbuf->slot);
auxputs(" ");
#endif
if (dbuf->id == 0){
if ((pp = dbuf->buf.rp->pp) != NULL){
pp->drv = NULL;
dbuf->buf.rp->pp = NULL;
}
dst = dbuf->buf.rp->buf;
} else {
if ((pp = dbuf->buf.bp->pp) != NULL){
pp->drv = NULL;
dbuf->buf.bp->pp = NULL;
}
dst = dbuf->buf.bp->buf;
}
dst += dbuf->slot * sizeof (struct dirent);
xcopy(laddr(dir), dst, sizeof (struct dirent));
dbuf->slot++;
dir_dirty(dbuf);
return (0);
}
dir_bread(struct dirbuf *dir)
{
struct drvinfo far *d;
u_short id;
struct rdirbuf far *rp;
struct buffer far *bp;
int size;
d = dir->drv;
id = dir->id;
#ifdef DEBUG
auxputs("dir_bread:");
auxprinthex((u_long)id);
auxputs(",");
auxprinthex((u_long)dir->fat);
auxputs(" ");
#endif
if (id == 0){ /* root dir */
if ((rp = root_read(d, dir->fat)) == NULL)
return (-1);
dir->buf.rp = rp;
dir->n_entry = rp->n_entry;
#ifdef DEBUG
auxputs("done.\r\n");
#endif
return (0);
}
if ((bp = bread(d, id, dir->fat, BUF_DIR)) == NULL)
return (-1);
dir->buf.bp = bp;
dir->n_entry = d->dirsec * d->cluster;
#ifdef DEBUG
auxputs("done.\r\n");
#endif
return (0);
}
dir_next(struct dirbuf *dir)
{
struct rdirbuf far *rp;
struct buffer far *bp;
struct drvinfo far *d;
u_short next, size;
#ifdef DEBUG
auxputs("dir_next: ");
#endif
if (dir->id == 0){ /* root dir */
dir->fat += N_RDIR_ENTRY;
if ((rp = root_read(dir->drv, dir->fat)) == NULL)
return (-1);
dir->buf.rp = rp;
dir->n_entry = rp->n_entry;
return (0);
}
d = dir->drv;
if ((next = fat_decode(d, dir->fat)) == 1){
#ifdef DEBUG_ERR
auxputs("dir_next: fat chain error.\r\n");
#endif
d->fat_error++;
return (-1);
}
if (next >= d->last_fat)
return (-1);
dir->fat = next;
if ((bp = bread(d, dir->id, next, BUF_DIR)) == NULL)
return (-1);
dir->buf.bp = bp;
return (0);
}
dir_bwrite(struct drvinfo far *d, u_short id, u_short fat, struct dirbuf *dir)
{
struct rdirbuf far *rp;
struct buffer far *bp;
int size;
if ((bp = bwrite(d, id, fat, BUF_DIR, TRUE)) == NULL)
return (-1);
dir->buf.bp = bp;
dir->n_entry = d->dirsec * d->cluster;
dir->drv = d;
dir->id = id;
dir->fat = fat;
dir->slot = 0;
return (0);
}
/*
* Make a directory entry. Builds a directory entry based on the
* name, attribute, starting cluster number, and size. Returns a pointer
* to a static directory structure.
*/
void mk_entry(struct dirent far *dir, u_char *filename, u_char attr,
u_short fat, u_long size, u_long now)
{
int i;
copy_to(filename, 11, dir->name);
dir->attr = attr;
for (i = 0; i < 10; i++)
dir->reserv[i] = 0x00;
dir->time = now;
dir->start = fat;
dir->size = size;
}
/*
* Make a subdirectory grow in length. Only subdirectories (not root)
* may grow. Returns a 0 on success, 1 on failure (disk full), or -1
* on error.
*/
dir_grow(struct drvinfo far *d, u_short id, u_short fat)
{
u_short new, entry;
u_long addr;
struct dirbuf dBuf;
struct dirent dir;
if ((new = new_fat(d, 0)) == 1){
#ifdef DEBUG_ERR
auxputs("dir_grow: FAT error\r\n");
#endif
d->fat_error++;
return(-1);
}
fat = last_fat(d, fat);
if (fat_encode(d, fat, new)) /* grow OK ? */
return (-1);
if (fat_encode(d, new, d->end_fat)) /* mark EOF OK ? */
return (-1);
d->freearea--;
/* clear new directory cluster */
if (dir_bwrite(d, id, new, &dBuf) < 0)
return (-1);
for (entry = 0; entry < dBuf.n_entry; entry++){
bzero(&dir, sizeof (struct dirent));
dir_write(&dBuf, (struct dirent far *)&dir);
}
dir_dirty(&dBuf);
return(0);
}
void dir_dirty(struct dirbuf *p)
{
if (p->id == 0) /* root dir */
p->buf.rp->dirty = TRUE;
else
p->buf.bp->dirty = TRUE;
}
void dir_flush(int invalidate)
{
flush_root(NULL, invalidate);
flush_buffer(NULL, 0, BUF_DIR, invalidate);
}